Rework the event translation to look more like X11
authorRichard Hult <richard@imendio.com>
Fri, 16 Jan 2009 11:21:46 +0000 (12:21 +0100)
committerAlexander Larsson <alex@localhost.localdomain>
Thu, 2 Apr 2009 08:15:24 +0000 (10:15 +0200)
Put the event in the queue with a pending flag, remove again if not
handled.

gdk/quartz/gdkevents-quartz.c

index d24c49fb0219b2c23ae83866fc43a6be9b792f75..57910125c881770b0c7b5bd5a40106e482284713 100644 (file)
@@ -317,50 +317,27 @@ append_event (GdkEvent *event)
   _gdk_event_queue_append (_gdk_display, event);
 }
 
-static GdkFilterReturn
-apply_filters (GdkWindow  *window,
-              NSEvent    *nsevent,
-              GList      *filters)
+static gint
+gdk_event_apply_filters (NSEvent *nsevent,
+                        GdkEvent *event,
+                        GList *filters)
 {
-  GdkFilterReturn result = GDK_FILTER_CONTINUE;
-  GdkEvent *event;
-  GList *node;
   GList *tmp_list;
-
-  event = gdk_event_new (GDK_NOTHING);
-  if (window != NULL)
-    event->any.window = g_object_ref (window);
-  ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
-
-  /* I think GdkFilterFunc semantics require the passed-in event
-   * to already be in the queue. The filter func can generate
-   * more events and append them after it if it likes.
-   */
-  node = _gdk_event_queue_append (_gdk_display, event);
+  GdkFilterReturn result;
   
   tmp_list = filters;
+
   while (tmp_list)
     {
-      GdkEventFilter *filter = (GdkEventFilter *) tmp_list->data;
+      GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
       
       tmp_list = tmp_list->next;
       result = filter->function (nsevent, event, filter->data);
-      if (result != GDK_FILTER_CONTINUE)
-       break;
+      if (result !=  GDK_FILTER_CONTINUE)
+       return result;
     }
 
-  if (result == GDK_FILTER_CONTINUE || result == GDK_FILTER_REMOVE)
-    {
-      _gdk_event_queue_remove_link (_gdk_display, node);
-      g_list_free_1 (node);
-      gdk_event_free (event);
-    }
-  else /* GDK_FILTER_TRANSLATE */
-    {
-      ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
-      fixup_event (event);
-    }
-  return result;
+  return GDK_FILTER_CONTINUE;
 }
 
 /* Checks if the passed in window is interested in the event mask, and
@@ -1412,13 +1389,13 @@ find_window_for_ns_event (NSEvent *nsevent,
   return NULL;
 }
 
-static GdkEvent *
-create_button_event (GdkWindow *window, 
-                     NSEvent   *nsevent,
-                    gint       x,
-                     gint       y)
+static void
+fill_button_event (GdkWindow *window,
+                   GdkEvent  *event,
+                   NSEvent   *nsevent,
+                   gint       x,
+                   gint       y)
 {
-  GdkEvent *event;
   GdkEventType type;
   gint state;
   gint button;
@@ -1444,7 +1421,7 @@ create_button_event (GdkWindow *window,
   
   button = get_mouse_button_from_ns_event (nsevent);
 
-  event = gdk_event_new (type);
+  event->any.type = type;
   event->button.window = window;
   event->button.time = get_time_from_ns_event (nsevent);
   event->button.x = x;
@@ -1456,17 +1433,15 @@ create_button_event (GdkWindow *window,
   convert_window_coordinates_to_root (window, x, y, 
                                      &event->button.x_root,
                                      &event->button.y_root);
-
-  return event;
 }
 
-static GdkEvent *
-create_motion_event (GdkWindow *window, 
-                     NSEvent   *nsevent, 
-                     gint       x, 
-                     gint       y)
+static void
+fill_motion_event (GdkWindow *window,
+                   GdkEvent  *event,
+                   NSEvent   *nsevent,
+                   gint       x,
+                   gint       y)
 {
-  GdkEvent *event;
   GdkEventType type;
   GdkModifierType state = 0;
 
@@ -1486,7 +1461,7 @@ create_motion_event (GdkWindow *window,
 
   state |= get_keyboard_modifiers_from_ns_event (nsevent);
 
-  event = gdk_event_new (type);
+  event->any.type = type;
   event->motion.window = window;
   event->motion.time = get_time_from_ns_event (nsevent);
   event->motion.x = x;
@@ -1497,19 +1472,17 @@ create_motion_event (GdkWindow *window,
   event->motion.device = _gdk_display->core_pointer;
   convert_window_coordinates_to_root (window, x, y,
                                      &event->motion.x_root, &event->motion.y_root);
-  
-  return event;
 }
 
-static GdkEvent *
-create_scroll_event (GdkWindow          *window, 
-                     NSEvent            *nsevent, 
-                     GdkScrollDirection  direction)
+static void
+fill_scroll_event (GdkWindow          *window,
+                   GdkEvent           *event,
+                   NSEvent            *nsevent,
+                   GdkScrollDirection  direction)
 {
-  GdkEvent *event;
   NSPoint point;
   
-  event = gdk_event_new (GDK_SCROLL);
+  event->any.type = GDK_SCROLL;
   event->scroll.window = window;
   event->scroll.time = get_time_from_ns_event (nsevent);
 
@@ -1523,21 +1496,19 @@ create_scroll_event (GdkWindow          *window,
 
   event->scroll.direction = direction;
   event->scroll.device = _gdk_display->core_pointer;
-  
-  return event;
 }
 
-static GdkEvent *
-create_key_event (GdkWindow    *window, 
-                  NSEvent      *nsevent, 
-                  GdkEventType  type)
+static void
+fill_key_event (GdkWindow    *window,
+                GdkEvent     *event,
+                NSEvent      *nsevent,
+                GdkEventType  type)
 {
-  GdkEvent *event;
   GdkEventPrivate *priv;
   gchar buf[7];
   gunichar c = 0;
 
-  event = gdk_event_new (type);
+  event->any.type = type;
 
   priv = (GdkEventPrivate *) event;
   priv->windowing_data = [nsevent retain];
@@ -1644,7 +1615,6 @@ create_key_event (GdkWindow    *window,
          event->key.window,
          event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
          event->key.keyval));
-  return event;
 }
 
 GdkEventMask 
@@ -1654,13 +1624,13 @@ _gdk_quartz_events_get_current_event_mask (void)
 }
 
 static gboolean
-gdk_event_translate (NSEvent *nsevent)
+gdk_event_translate (GdkEvent *event,
+                     NSEvent  *nsevent)
 {
   NSWindow *nswindow;
   GdkWindow *window;
-  GdkFilterReturn result;
-  GdkEvent *event;
   int x, y;
+  gboolean return_val;
 
   /* There is no support for real desktop wide grabs, so we break
    * grabs when the application loses focus (gets deactivated).
@@ -1705,17 +1675,17 @@ gdk_event_translate (NSEvent *nsevent)
 
   nswindow = [nsevent window];
 
-  /* Apply any global filters. */
   if (_gdk_default_filters)
     {
-      result = apply_filters (NULL, nsevent, _gdk_default_filters);
+      /* Apply global filters */
+      GdkFilterReturn result;
 
-      /* If result is GDK_FILTER_CONTINUE, we continue as if nothing
-       * happened. If it is GDK_FILTER_REMOVE,
-       * we return TRUE and won't send the message to Quartz.
-       */
-      if (result == GDK_FILTER_REMOVE)
-       return TRUE;
+      result = gdk_event_apply_filters (nsevent, event, _gdk_default_filters);
+      if (result != GDK_FILTER_CONTINUE)
+        {
+          return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+          goto done;
+        }
     }
 
   /* Ignore events for no window or ones not created by GDK. */
@@ -1745,9 +1715,26 @@ gdk_event_translate (NSEvent *nsevent)
     return FALSE;
 
   /* Apply any window filters. */
-  result = apply_filters (window, nsevent, ((GdkWindowObject *) window)->filters);
-  if (result == GDK_FILTER_REMOVE)
-    return TRUE;
+  if (GDK_IS_WINDOW (window))
+    {
+      GdkWindowObject *filter_private = (GdkWindowObject *) window;
+      GdkFilterReturn result;
+
+      if (filter_private->filters)
+       {
+         g_object_ref (window);
+
+         result = gdk_event_apply_filters (nsevent, event, filter_private->filters);
+
+         g_object_unref (window);
+
+         if (result != GDK_FILTER_CONTINUE)
+           {
+             return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+             goto done;
+           }
+       }
+    }
 
   /* We need the appliction to be activated on clicks so that popups
    * like context menus get events routed properly. This is handled
@@ -1762,6 +1749,8 @@ gdk_event_translate (NSEvent *nsevent)
 
   current_event_mask = get_event_mask_from_ns_event (nsevent);
 
+  return_val = TRUE;
+
   switch ([nsevent type])
     {
     case NSLeftMouseDown:
@@ -1783,17 +1772,13 @@ gdk_event_translate (NSEvent *nsevent)
          }
       }
       
-      event = create_button_event (window, nsevent, x, y);
-      append_event (event);
-      
-      _gdk_event_button_generate (_gdk_display, event);
+      fill_button_event (window, event, nsevent, x, y);
       break;
 
     case NSLeftMouseUp:
     case NSRightMouseUp:
     case NSOtherMouseUp:
-      event = create_button_event (window, nsevent, x, y);
-      append_event (event);
+      fill_button_event (window, event, nsevent, x, y);
       
       /* Ungrab implicit grab */
       if (_gdk_quartz_pointer_grab_window && pointer_grab_implicit)
@@ -1804,8 +1789,7 @@ gdk_event_translate (NSEvent *nsevent)
     case NSRightMouseDragged:
     case NSOtherMouseDragged:
     case NSMouseMoved:
-      event = create_motion_event (window, nsevent, x, y);
-      append_event (event);
+      fill_motion_event (window, event, nsevent, x, y);
       break;
 
     case NSScrollWheel:
@@ -1827,15 +1811,7 @@ gdk_event_translate (NSEvent *nsevent)
        else
          direction = GDK_SCROLL_UP;
 
-       while (dy > 0.0)
-         {
-           event = create_scroll_event (window, nsevent, direction);
-           append_event (event);
-           dy--;
-
-            /* Ignore the delta for now, things get too slow when the events queue up. */
-            break;
-         }
+        fill_scroll_event (window, event, nsevent, direction);
 
        /* Now do x events */
        if (dx < 0.0)
@@ -1846,16 +1822,7 @@ gdk_event_translate (NSEvent *nsevent)
        else
          direction = GDK_SCROLL_LEFT;
 
-       while (dx > 0.0)
-         {
-           event = create_scroll_event (window, nsevent, direction);
-           append_event (event);
-           dx--;
-            
-            /* Ignore the delta for now, things get too slow when the events queue up. */
-            break;
-         }
-
+        fill_scroll_event (window, event, nsevent, direction);
       }
       break;
 
@@ -1867,11 +1834,9 @@ gdk_event_translate (NSEvent *nsevent)
 
         type = _gdk_quartz_keys_event_type (nsevent);
         if (type == GDK_NOTHING)
-          return FALSE;
-        
-        event = create_key_event (window, nsevent, type);
-        append_event (event);
-        return TRUE;
+          return_val = FALSE;
+        else
+          fill_key_event (window, event, nsevent, type);
       }
       break;
 
@@ -1880,25 +1845,63 @@ gdk_event_translate (NSEvent *nsevent)
       break;
     }
 
-  return FALSE;
+ done:
+  if (return_val)
+    {
+      if (event->any.window)
+       g_object_ref (event->any.window);
+      if (((event->any.type == GDK_ENTER_NOTIFY) ||
+          (event->any.type == GDK_LEAVE_NOTIFY)) &&
+         (event->crossing.subwindow != NULL))
+       g_object_ref (event->crossing.subwindow);
+    }
+  else
+    {
+      /* Mark this event as having no resources to be freed */
+      event->any.window = NULL;
+      event->any.type = GDK_NOTHING;
+    }
+
+  return return_val;
 }
 
 void
 _gdk_events_queue (GdkDisplay *display)
 {  
-  NSEvent *event;
+  NSEvent *nsevent;
 
-  event = _gdk_quartz_event_loop_get_pending ();
-  if (event)
+  nsevent = _gdk_quartz_event_loop_get_pending ();
+  if (nsevent)
     {
-      if (!gdk_event_translate (event))
+      GdkEvent *event;
+      GList *node;
+
+      event = gdk_event_new (GDK_NOTHING);
+
+      event->any.window = NULL;
+      event->any.send_event = FALSE;
+
+      ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
+
+      node = _gdk_event_queue_append (display, event);
+
+      if (gdk_event_translate (event, nsevent))
+        {
+         ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
+          _gdk_windowing_got_event (display, node, event);
+        }
+      else
         {
+         _gdk_event_queue_remove_link (display, node);
+         g_list_free_1 (node);
+         gdk_event_free (event);
+
           GDK_THREADS_LEAVE ();
-          [NSApp sendEvent:event];
+          [NSApp sendEvent:nsevent];
           GDK_THREADS_ENTER ();
         }
 
-      _gdk_quartz_event_loop_release_event (event);
+      _gdk_quartz_event_loop_release_event (nsevent);
     }
 }